#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>

void diep(char *s)
{
	perror(s);
	exit(1);
}

double difftv(struct timeval *start, struct timeval *end) {
  double retval;

  retval = end->tv_sec - start->tv_sec;

  if(end->tv_usec >= start->tv_usec) {
    retval += ((double)(end->tv_usec - start->tv_usec)) / 1000000;
  } else {
    retval -= 1.0;
    retval += ((double)(end->tv_usec + 1000000) - start->tv_usec) / 1000000;
  }

  return retval;
}


int main(int argc, char **argv)
{
  struct sockaddr_in si_me, si_other;
  int c, s, i, slen=sizeof(si_other);
  int ret;
  char *buf;

  int buflen = 1024*32;
  int port = 9930;

  unsigned int bytes_count;

  while((c = getopt(argc, argv, "l:p:")) != -1) {
    switch(c) {
    case 'l':
      buflen = atoi(optarg);
      break;
      
    case 'p':
      port = atoi(optarg);
      break; 
    }
  }  

  buf = malloc(buflen*sizeof(char));

  if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
    diep("socket");
  
  memset((char *) &si_me, 0, sizeof(si_me));
  si_me.sin_family = AF_INET;
  si_me.sin_port = htons(port);
  si_me.sin_addr.s_addr = htonl(INADDR_ANY);
  if (bind(s, &si_me, sizeof(si_me))==-1)
    diep("bind");

  struct timeval start_time, end_time;


  bytes_count = 0;

  while (1) {
    ret = recvfrom(s, buf, buflen, 0, &si_other, &slen);
    
    if (!bytes_count)
      gettimeofday(&start_time, NULL);
    
    if (ret <= 0) {
      if (ret < 0)
	diep("recvfrom()");
      else
	break;
    }
    
    bytes_count += ret;

    //printf("Received packet (%d) from %s:%d\nData: %s\n\n", ret,
    //inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port), buf);

    i = atoi(buf);
    if (i==0)
      break;
  }
  
  gettimeofday(&end_time, NULL);

  printf("Time: %f seconds\n", difftv(&start_time, &end_time));
  printf("Speed: %f Mb/s\n", (((double) bytes_count*8)/difftv(&start_time, &end_time))/1024/1024);

  close(s);
  return 0;
}
